/*
** $Id: lparser.h $
** Lua 解析器
** See Copyright Notice in lua.h
*/

#ifndef lparser_h
#define lparser_h

#include "llimits.h"
#include "lobject.h"
#include "lzio.h"


/*
** 表达式和变量描述
** 变量和表达式的代码生成可以延迟以允许优化; 一个 'expdesc' 结构描述一个可能延迟的变量/表达式。
** 它有一个 "main" 值的描述加上一个也可以产生其值的条件跳转(conditional jumps)列表 (由 short-circuit 操作生成 'and'/'or')
*/

/* 变量/表达式的类型 */
typedef enum {
  VVOID,  /* 当 'expdesc' 描述列表的最后一个表达式时，这个类型意味着一个空列表(因此，没有表达式) */
  VNIL,  /* 常量 nil */
  VTRUE,  /* 常量 true */
  VFALSE,  /* 常量 false */
  VK,  /* 'k' 中的常量; info = 常量在 'k' 中的索引 */
  VKFLT,  /* floating 常量; nval = 数字浮点值 */
  VKINT,  /* integer 常量; ival = 数字整数 */
  VKSTR,  /* string 常量; strval = TString 地址; (字符串由词法分析器固定) */
  VNONRELOC,  /* 表达式在一个固定的寄存器中有它的值； info = result register */
  VLOCAL,  /* 局部变量; var.ridx = 寄存器索引; var.vidx = 'actvar.arr' 中的相对索引  */
  VUPVAL,  /* upvalue 变量; info = 上值在 'upvalues' 中的索引 */
  VCONST,  /* 编译时 <const> 变量; info = 在 'actvar.arr' 中的绝对索引 */
  VINDEXED,  /* 索引(indexed)变量;
          ind.t = table register;
          ind.idx = key's R index */
  VINDEXUP,  /* 索引(indexed) upvalue;
                ind.t = table upvalue;
                ind.idx = key's K index */
  VINDEXI, /* 常量整数索引(indexed) 变量;
                ind.t = table register;
                ind.idx = key's value */
  VINDEXSTR, /* 字符串字面量索引(indexed) 变量;
                ind.t = table register;
                ind.idx = key's K index */
  VJMP,  /* 表达式是一个 test/comparison;
            info = 对应跳转指令的 pc */
  VRELOC,  /* 表达式可以将结果放入任何寄存器; info = instruction pc */
  VCALL,  /* 表达式是一个函数调用； info = instruction pc */
  VVARARG  /* 可变参表达式; info = instruction pc */
} expkind;


#define vkisvar(k)	(VLOCAL <= (k) && (k) <= VINDEXSTR)
#define vkisindexed(k)	(VINDEXED <= (k) && (k) <= VINDEXSTR)


typedef struct expdesc {
  expkind k;
  union {
    lua_Integer ival;    /* 用于 VKINT */
    lua_Number nval;  /* 用于 VKFLT */
    TString *strval;  /* 用于 VKSTR */
    int info;  /* 用于一般情况 */
    struct {  /* 用于索引变量 */
      short idx;  /* 索引 (R or "long" K) */
      lu_byte t;  /* 表 (register or upvalue) */
    } ind;
    struct {  /* 用于局部变量 */
      lu_byte ridx;  /* 持有该变量的寄存器(register) */
      unsigned short vidx;  /* 编译索引 ('actvar.arr')  */
    } var;
  } u;
  int t;  /* 'exit when true' 的 patch list */
  int f;  /* 'exit when false' 的 patch list */
} expdesc;


/* 变量类型 */
#define VDKREG		0   /* 常规变量 */
#define RDKCONST	1   /* 常量 local a<const> */
#define RDKTOCLOSE	2   /* 待关闭变量 local a<close> */
#define RDKCTC		3   /* 编译时常量 */

/* 活跃局部变量(active local variable)描述 */
typedef union Vardesc {
  struct {
    TValuefields;  /* 常量值 (如果他是编译时常量) */
    lu_byte kind;
    lu_byte ridx;  /* 持有该变量的register(寄存器) */
    short pidx;  /* 变量在 Proto's 'locvars' 数组中的索引 */
    TString *name;  /* 变量名称 */
  } vd;
  TValue k;  /* 常量值 */
} Vardesc;



/* goto 语句和 label 语句 */
typedef struct Labeldesc {
  TString *name;  /* label 标识符 */
  int pc;  /* 代码中的位置 */
  int line;  /* 出现的行号 */
  lu_byte nactvar;  /* 该位置的 active variables 数量 */
  lu_byte close;  /* goto that escapes upvalues */
} Labeldesc;


/* labels / gotos 的列表 */
typedef struct Labellist {
  Labeldesc *arr;  /* 数组 */
  int n;  /* 使用中的元素个数 */
  int size;  /* 数组大小 */
} Labellist;


/* 用于解析器的动态结构 */
typedef struct Dyndata {
  struct {  /* 所有活跃的局部变量列表 */
    Vardesc *arr;
    int n;
    int size;
  } actvar;
  Labellist gt;  /* gotos 列表 */
  Labellist label;   /* active labels 列表 */
} Dyndata;


/* control of blocks */
struct BlockCnt;  /* defined in lparser.c */


/* 用于给定函数生成代码的状态机 */
typedef struct FuncState {
  Proto *f;  /* 当前函数头 */
  struct FuncState *prev;  /* enclosing function */
  struct LexState *ls;  /* 词法状态 */
  struct BlockCnt *bl;  /* 当前语句块链 */
  int pc;  /* 下一个code位置 (等价于 'ncode') */
  int lasttarget;   /* 最后一个 'jump label' 的 'label' */
  int previousline;  /* 保存在 'lineinfo' 中的前一行 */
  int nk;  /* 'k' 元素的数量 */
  int np;  /* 'p' 元素的数量 */
  int nabslineinfo;  /* 'abslineinfo' 元素的数量 */
  int firstlocal;  /* 第一个局部变量的索引(在 Dyndata 数组中) */
  int firstlabel;  /* 第一个 label 的索引 ('dyd->label->arr') */
  short ndebugvars;  /* 'f->locvars' 元素的数量 */
  lu_byte nactvar;  /* active local variables(活跃的局部变量) 的数量 */
  lu_byte nups;  /* upvalues 的数量 */
  lu_byte freereg;  /* 第一个空闲的寄存器 */
  lu_byte iwthabs;  /* 从上一个绝对行信息(absolute line info) 以来发出的指令 */
  lu_byte needclose;  /* 函数返回时需要关闭upvalues */
} FuncState;


LUAI_FUNC int luaY_nvarstack (FuncState *fs);
LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
                                 Dyndata *dyd, const char *name, int firstchar);


#endif
